package de.pass.ch.preprocessing;

import java.io.IOException;
import java.util.Properties;

public class WeightCalculation {

	/** coefficient for edge difference */
	protected int edgeDiffMult;

	/** coefficient for number of new edges */
	protected int newEdgesMult;

	/** coefficient for deleted neighbors */
	protected int delNeighbMult;

	/** coefficient for search space size of local searches for contraction */
	protected double searchSpaceMult;

	/** coefficient for relative betweenness */
	protected int betweennessAdd;

	/** coefficient for relative reach */
	protected int reachAdd;

	/** coefficient for Voronoi region size */
	protected int voronoiMult;

	/** coefficient for upper bound on search paths hops */
	protected int searchPathHopBorderMult;

	/**
	 * in combination with searchPathHopBorderMult does calculate an upper bound
	 * on the costs for a time-dependend search, requested by Veit Batz
	 */
	protected boolean searchPathHopBorderOriginalEdges;

	/** coefficient for sum of original edges new shortcuts represent */
	protected int shortcutOriginalEdgeSumMult;

	/** limit of settled nodes in local searches during weight calculation */
	protected int maxSettledApprox;

	/** limit of settled nodes in local searches during contraction */
	protected int maxSettledElim;

	/** hop-/degree-limits */
	protected float[] maxHops;

	/**
	 * lazy updates, parameter also specifies the check intervals for complete
	 * recalculation of priority queue
	 */
	protected int lazyUpdateRecalcLimit;

	/**
	 * perform update on all affected nodes after contraction this only works
	 * with hop-limits and is really slow should only be used for testing
	 */
	protected boolean updateHops;

	/** wheter to use local edge reduction (recommended) */
	protected boolean localReduceEdges;

	public static final byte ECO_MODE = 0;
	public static final byte AGG_MODE = 1;
	public static final byte OWN_MODE = 2;

	public WeightCalculation(byte mode) {
		loadProperties(mode);
	}

	private void loadProperties(byte mode) {
		String file = "nodeOrder_";
		file += mode == ECO_MODE ? "eco" : mode == AGG_MODE ? "agg" : "own";
		file += ".properties";
		Properties prop = new Properties();

		try {
			// load properties file
			prop.load(getClass().getClassLoader().getResourceAsStream(file));

			// load Integers
			edgeDiffMult = Integer.parseInt(prop.getProperty("edgeDiffMult"));
			newEdgesMult = Integer.parseInt(prop.getProperty("newEdgesMult"));
			delNeighbMult = Integer.parseInt(prop.getProperty("delNeighbMult"));
			betweennessAdd = Integer.parseInt(prop
					.getProperty("betweennessAdd"));
			reachAdd = Integer.parseInt(prop.getProperty("reachAdd"));
			voronoiMult = Integer.parseInt(prop.getProperty("voronoiMult"));
			searchPathHopBorderMult = Integer.parseInt(prop
					.getProperty("searchPathHopBorderMult"));
			shortcutOriginalEdgeSumMult = Integer.parseInt(prop
					.getProperty("shortcutOriginalEdgeSumMult"));
			maxSettledApprox = Integer.parseInt(prop
					.getProperty("maxSettledApprox"));
			maxSettledElim = Integer.parseInt(prop
					.getProperty("maxSettledElim"));
			lazyUpdateRecalcLimit = Integer.parseInt(prop
					.getProperty("lazyUpdateRecalcLimit"));

			// load double
			searchSpaceMult = Double.parseDouble(prop
					.getProperty("searchSpaceMult"));

			// load booleans
			searchPathHopBorderOriginalEdges = Boolean.parseBoolean(prop
					.getProperty("searchPathHopBorderOriginalEdges"));
			updateHops = Boolean.parseBoolean(prop.getProperty("updateHops"));
			localReduceEdges = Boolean.parseBoolean(prop
					.getProperty("localReduceEdges"));

			// load double[]
			String mHops = prop.getProperty("maxHops");

			if (mHops == null)
				throw new IOException("property 'maxHops' nicht gefunden!");

			String[] floats = mHops.split(",");

			if (floats.length == 1 && "".equals(floats[0].trim())) {
				maxHops = new float[0];
				return;
			}

			maxHops = new float[floats.length];
			for (int i = 0; i < floats.length; i++) {
				maxHops[i] = Float.parseFloat(floats[i]);
			}

		} catch (IOException ex) {
			System.out.println("Fehler beim Lesen der properties-Datei: "
					+ file);
			ex.printStackTrace();
		}
	}

}
